package net.dgg.zz.common.utils;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * @Description 异常信息工具类
 * @Version 1.0.0
 * @Author Created by yan.x on 2019-02-14 .
 * @Copyright © dgg group.All Rights Reserved.
 **/
public final class ExceptionUtils {

    private final static Logger _log = LoggerFactory.getLogger(net.dgg.zz.common.utils.ExceptionUtils.class);

    /**
     * 输出异常堆栈
     *
     * @param e
     * @return
     */
    public static String getMessage(Exception e) {
        StringWriter sw = null;
        PrintWriter pw = null;
        try {
            sw = new StringWriter();
            pw = new PrintWriter(sw);
            // 将出错的栈信息输出到printWriter中
            e.printStackTrace(pw);
            pw.flush();
            sw.flush();
        } finally {
            if (sw != null) {
                try {
                    sw.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (pw != null) {
                pw.close();
            }
        }
        return sw.toString();
    }

    /**
     * info日志记录
     *
     * @param mark   : 标志信息
     * @param params : 请求参数
     */
    public static void info(String mark, Object... params) {
        try {
            StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
            String className = stackTraceElement.getClassName();
            String methodName = stackTraceElement.getMethodName();
            Logger logger = LoggerFactory.getLogger(className);
            if (logger.isInfoEnabled()) {
                logger.info("<====== {}.{} [ mark：{} ][ params：{} ]", className, methodName, mark, JSONUtils.toJSONString(params));
            }
        } catch (Exception e1) {
        }
    }

    /**
     * debug日志记录
     *
     * @param format : 消息模版
     * @param params : 请求参数
     */
    public static void debug(String format, Object... params) {
        try {
            StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
            Logger logger = LoggerFactory.getLogger(stackTraceElement.getClassName());
            if (logger.isDebugEnabled()) {
                logger.debug(format, params);
            }
        } catch (Exception e1) {
        }
    }

    /**
     * 异常日志记录
     *
     * @param e      : 异常信息
     * @param mark   : 标志/请求api信息
     * @param params : 请求参数
     */
    public static void error(Exception e, String mark, Object... params) {
        try {
            StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
            String className = stackTraceElement.getClassName();
            String methodName = stackTraceElement.getMethodName();
            String message = getMessage(e);
            Logger logger = LoggerFactory.getLogger(className);
            if (logger.isErrorEnabled()) {
                logger.error("<== {}.{} [ time：{} ][ mark：{} ][ params：{} ][ excption: {} ] ", className, methodName, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), mark, JSONUtils.toJSONString(params), message);
            }
        } catch (Exception e1) {
            _log.error(getMessage(e));
        }
    }

    /**
     * 异常日志记录
     *
     * @param mark   : 标志/请求api信息
     * @param params : 请求参数
     */
    public static void error(String mark, String message, Object... params) {
        try {
            StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
            String className = stackTraceElement.getClassName();
            String methodName = stackTraceElement.getMethodName();
            Logger logger = LoggerFactory.getLogger(className);
            if (logger.isErrorEnabled()) {
                logger.error("<== {}.{} [ time：{} ][ mark：{} ][ params：{} ][ excption: {} ] ", className, methodName, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), mark, JSONUtils.toJSONString(params), message);
            }
        } catch (Exception e1) {
            _log.error(getMessage(e1));
        }
    }

    /**
     * 异常日志记录
     *
     * @param mark   : 标志/请求api信息
     * @param params : 请求参数
     */
    public static void error(String mark, String message, List params) {
        try {
            StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
            String className = stackTraceElement.getClassName();
            String methodName = stackTraceElement.getMethodName();
            Logger logger = LoggerFactory.getLogger(className);
            if (logger.isErrorEnabled()) {
                logger.error("<== {}.{} [ time：{} ][ mark：{} ][ params：{} ][ excption: {} ] ", className, methodName, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), mark, JSONUtils.toJSONString(params), message);
            }
        } catch (Exception e1) {
            _log.error(getMessage(e1));
        }
    }

    /**
     * 调用异常日志记录
     *
     * @param mark   : 标志/请求api信息
     * @param params : 请求参数
     */
    public static void callError(Exception e, String mark, String apiPath, Object... params) {
        try {
            StackTraceElement stackTraceElement = Thread.currentThread().getStackTrace()[2];
            String className = stackTraceElement.getClassName();
            Logger logger = LoggerFactory.getLogger(className);
            if (logger.isErrorEnabled()) {
                if (null == e) {
                    logger.error("<== 请求 {} 失败 [ time：{} ][ mark：{} ][ api：{} ][ params：{} ]", mark, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), mark, apiPath, null == params ? null : JSONUtils.toJSONString(params));
                } else {
                    logger.error("<== 请求 {} 失败 [ time：{} ][ mark：{} ][ api：{} ][ params：{} ][ excption: {} ] ", mark, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), mark, apiPath, null == params ? null : JSONUtils.toJSONString(params), e);
                }
            }
        } catch (Exception e1) {
            _log.error(getMessage(e1));
        }
    }

    /**
     * 获取 {@link ConstraintViolationException} 异常信息
     *
     * @param ex
     * @return
     */
    public static String getConstraintViolationExceptionMessage(ConstraintViolationException ex) {
        Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
        if (CollectionUtils.isEmpty(constraintViolations)) {
            return "操作失败";
        }
        StringBuilder msgBuilder = new StringBuilder();
        for (ConstraintViolation constraintViolation : constraintViolations) {
            msgBuilder.append(constraintViolation.getMessage()).append(",");
        }
        String errorMessage = msgBuilder.toString();
        if (errorMessage.length() > 1) {
            errorMessage = errorMessage.substring(0, errorMessage.length() - 1);
        }
        return errorMessage;
    }
}